#include "Socket.h"
#include <cstring>    // strerror
#include <unistd.h>   // close
#include <stdio.h>    // printf


int createnonblocking()
{
    int listenfd = socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,IPPROTO_TCP);
    if(listenfd<0){
        printf("[ERROR] %s::%s (file: %s): listenfd is invalid\n", 
               __FILE__, __FUNCTION__, __FILE__);
        exit(-1);
    }
    return listenfd;
}

// 构造函数：使用现有文件描述符初始化
Socket::Socket(int fd) : fd_(fd)
{
    if (fd < 0) {
        printf("[ERROR] %s::%s (file: %s): Invalid file descriptor (%d)\n", 
               __FILE__, __FUNCTION__, __FILE__, fd);
    }
}

// 析构函数：关闭文件描述符
Socket::~Socket()
{
    if (fd_ >= 0) {
        if (close(fd_) < 0) {
            printf("[ERROR] %s::%s (file: %s): Failed to close fd %d: %s\n",
                   __FILE__, __FUNCTION__, __FILE__, fd_, strerror(errno));
        }
    }
}

// 设置SO_REUSEADDR选项
void Socket::setreuseaddr(bool on)
{
    int optval = on ? 1 : 0;
    if (setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
        printf("[ERROR] %s::%s (file: %s): setsockopt SO_REUSEADDR failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
    }
}

// 设置SO_REUSEPORT选项
void Socket::setreuseport(bool on)
{
    int optval = on ? 1 : 0;
    if (setsockopt(fd_, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) < 0) {
        printf("[ERROR] %s::%s (file: %s): setsockopt SO_REUSEPORT failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
    }
}

// 设置TCP_NODELAY选项
void Socket::settcpnodelay(bool on)
{
    int optval = on ? 1 : 0;
    if (setsockopt(fd_, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)) < 0) {
        printf("[ERROR] %s::%s (file: %s): setsockopt TCP_NODELAY failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
    }
}

// 设置SO_KEEPALIVE选项
void Socket::setkeepalive(bool on)
{
    int optval = on ? 1 : 0;
    if (setsockopt(fd_, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0) {
        printf("[ERROR] %s::%s (file: %s): setsockopt SO_KEEPALIVE failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
    }
}

// 绑定地址到套接字
void Socket::bind(const InetAddress& servaddr)
{
    if (::bind(fd_, servaddr.addr(), sizeof(servaddr)) < 0) {
        printf("[ERROR] %s::%s (file: %s): bind failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
    }
}

// 开始监听连接
void Socket::listen(int nn)
{
    if (::listen(fd_, nn) < 0) {
        printf("[ERROR] %s::%s (file: %s): listen failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
    }
}

// 接受客户端连接
int Socket::accept(InetAddress& clientaddr)
{
    sockaddr_in peerAddr;
    socklen_t addrLen = sizeof(peerAddr);
    memset(&peerAddr, 0, sizeof(peerAddr));
    
    int clientFd = ::accept4(fd_, reinterpret_cast<sockaddr*>(&peerAddr), &addrLen,SOCK_NONBLOCK);
    //int clientFd = ::accept(fd_, reinterpret_cast<sockaddr*>(&peerAddr), &addrLen);
    if (clientFd < 0) {
        printf("[ERROR] %s::%s (file: %s): accept failed: %s\n",
               __FILE__, __FUNCTION__, __FILE__, strerror(errno));
        return -1;
    }
    
    clientaddr.setAddr(peerAddr);
    return clientFd;
}


int Socket::fd() const
{
    return fd_;
}